<html>
    <head>
        <script src="../modules.js"></script>
    </head>
    <body>
        <canvas id="canvas" width="400" height="400"></canvas>
        <script>
            require('environment.js').setDebug();
            with (require('base.js')) {
            with (require('xml.js')) {
            with (require('layout.js')) {
            with (require('scroll.js')) {
            initializer(function () {
            var canvas = $('canvas');
            var context = canvas.getContext('2d');

            var size = getSize(canvas);
            var dialation = 3.0;

            var r = .3;
            var t = r * .9;
            var u = r * .75;
            var paths = [
                [[-r, -r, r], [-r, r, r], [r, r, r], [r, -r, r], [-r, -r, r]],
                [[-r, -r, -r], [-r, r, -r], [r, r, -r], [r, -r, -r], [-r, -r, -r]],
                [[-r, -r, r], [-r, -r, -r]],
                [[-r, r, r], [-r, r, -r]],
                [[r, r, r], [r, r, -r]],
                [[r, -r, r], [r, -r, -r]],
                [[-t, -r, -r], [-t, -r, r], [-t, r, r], [-t, r, -r], [-t, -r, -r]],
                [[-r, -r, u], [-r, r, u]],
                [[r, -r, u], [r, r, u]],
                []
            ];
            var axesPaths = [
                [[-t, 0, 0], [t, 0, 0]],
                [[0, -t, 0], [0, t, 0]],
                [[0, 0, -t], [0, 0, t]]
            ];

            var identity = function (n) {
                var result = [];
                for (var i = 0; i < n; ++i) {
                    result[i] = [];
                    for (var j = 0; j < n; ++j) {
                        result[i][j] = i == j ? 1.0 : 0.0;
                    }
                }
                return result;
            };

            var identity2 = function () {
                return [[1.0, 0.0], [0.0, 1.0]];
            };

            var identity3 = function () {
                return [
                    [1.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0],
                    [0.0, 0.0, 1.0]
                ];
            };

            var transpose = function (matrix) {
                var result = [];
                for (var y = 0; y < matrix[0].length; y++) {
                    result[y] = [];
                    for (var x = 0; x < matrix.length; x++) {
                        result[y][x] = matrix[x][y];
                    }
                }
                return result;
            };

            var negative = function (matrix) {
                var result = [];
                for (var x = 0; x < matrix.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < matrix[x].length; y++) {
                        result[x][y] = -matrix[x][y];
                    }
                }
                return result;
            };

            var dot = function (matrix, scalar) {
                var result = [];
                for (var x = 0; x < a.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < b[0].length; y++) {
                        result[x][y] = matrix[x][y] * scalar;
                    }
                }
                return result;
            };

            var sum = function (a, b) {
                var result = [];
                for (var x = 0; x < a.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < b[0].length; y++) {
                        result[x][y] = a[x][y] + b[x][y];
                    }
                }
                return result;
            };

            var difference = function (a, b) {
                var result = [];
                for (var x = 0; x < a.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < b[0].length; y++) {
                        result[x][y] = a[x][y] - b[x][y];
                    }
                }
                return result;
            };

            var product = function (a, b) {
                var result = [];
                for (var x = 0; x < a.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < b[0].length; y++) {
                        var accumulator = 0;
                        for (var i = 0; i < b.length; i++) {
                            accumulator += a[x][i] * b[i][y];
                        }
                        result[x][y] = accumulator;
                    }
                }
                return result;
            };

            var axesX = function (matrix) {
                return [
                    [1.0, 0.0,          0.0         ],
                    [0.0, matrix[0][0], matrix[0][1]],
                    [0.0, matrix[1][0], matrix[1][1]]
                ];
            };

            var axesY = function (matrix) {
                return [
                    [matrix[0][0], 0.0, matrix[0][1]],
                    [0.0,          1.0, 0.0         ],
                    [matrix[1][0], 0.0, matrix[1][1]]
                ];
            };

            var axesZ = function (matrix) {
                return [
                    [matrix[0][0], matrix[0][1], 0.0],
                    [matrix[1][0], matrix[1][1], 0.0],
                    [0.0,          0.0,          1.0]
                ];
            };

            var rotate2 = function (theta) {
                with (Math) {
                    var sinTheta = sin(theta);
                    var cosTheta = cos(theta);
                    return [
                        [ cosTheta,  sinTheta],
                        [-sinTheta,  cosTheta]
                    ];
                }
            };

            var reflect2 = function (theta) {
                with (Math) {
                    var sinTheta = sin(theta);
                    var cosTheta = cos(theta);
                    return [
                        [ cosTheta,  sinTheta],
                        [ sinTheta, -cosTheta]
                    ];
                }
            };

            var rotate3 = function (vector, theta) {
            };

            var magnitude = function (vector) {
                var accumulator = 0;
                for (var i = 0; i < vector.length; i++) {
                    var cell = vector[i];
                    accumulator += cell * cell;
                }
                return Math.sqrt(accumulator);
            };

            var inverse = function (matrix) {
            };

            var lower = function (matrix) {
                var result = [];
                for (var x = 0; x < matrix.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < matrix.length; y++) {
                        result[x][y] = x >= y ? matrix[x][y] : 0;
                    }
                }
                return result;
            };

            var upper = function (matrix) {
                var result = [];
                for (var x = 0; x < matrix.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < matrix.length; y++) {
                        result[x][y] = y >= x ? matrix[x][y] : 0;
                    }
                }
                return result;
            };

            var diagonal = function (matrix) {
                var result = [];
                for (var x = 0; x < matrix.length; x++) {
                    result[x] = [];
                    for (var y = 0; y < matrix.length; y++) {
                        result[x][y] = y == x ? matrix[x][y] : 0;
                    }
                }
                return result;
            };

            var unit = function (vector) {
                return dot(vector, 1.0 / magnitude(vector));
            };

            var transform = function (vector, transform) {
                var result = [];
                for (var i = 0; i < vector.length; i++) {
                    var accumulator = 0;
                    for (var j = 0; j < vector.length; j++) {
                        accumulator += vector[j] * transform[i][j];
                    }
                    result[i] = accumulator;
                };
                return result;
            };

            var transformPaths = function (paths, matrix) {
                var result = [];
                for (var i = 0; i < paths.length; i++) {
                    var path = paths[i];
                    result[i] = [];
                    for (var j = 0; j < path.length; j++) {
                        var point = path[j];
                        result[i][j] = transform(point, matrix);
                    }
                }
                return result;
            };

            var projectPaths = function (paths) {
                var x = size.getX() / 2;
                var y = size.getY() / 2;
                var radius = min(size.getX(), size.getY()) / 2;
                var result = [];
                for (var i = 0; i < paths.length; i++) {
                    var path = paths[i];
                    result[i] = [];
                    for (var j = 0; j < path.length; j++) {
                        var point = path[j];
                        var factor = radius * Math.pow(dialation, point[2]);
                        result[i][j] = [
                            x + point[0] * factor,
                            y + point[1] * factor
                        ];
                    }
                }
                return result;
            };

            var drawPaths = function (paths) {
                context.save();
                for (var i = 0; i < paths.length; i++) {
                    var path = paths[i];
                    for (var j = 0; j < path.length - 1; j++) {
                        var a = path[j];
                        var b = path[j + 1];
                        context.beginPath();
                        context.moveTo(Math.round(a[0]), Math.round(a[1]));
                        context.lineTo(Math.round(b[0]), Math.round(b[1]));
                        context.stroke();
                    }
                }
                context.restore();
            }

            var tween = function (a, b) {
            };

            var i = 0;
            var axes = [0.0, 0.0, 0.0];
            paths[paths.length - 1] = axesPaths[i];
            setInterval(
                function () {
                    axes[i] += .01;
                    axes[0] %= 2.0;
                    axes[1] %= 1.0;
                    axes[2] %= 2.0;

                    var xform = product(
                        product(
                            axesZ(rotate2(Math.PI * 2 * axes[0])),
                            axesY(transpose(rotate2((Math.PI * 2 * axes[1]))))
                        ),
                        axesZ(rotate2(Math.PI * 2 * axes[2]))
                    );

                    context.clearRect(0, 0, size.getX(), size.getY());
                    drawPaths(
                        projectPaths(
                            transformPaths(
                                paths,
                                xform
                            )
                        )
                    );
                },
                0
            );

            setInterval(function () {
                i += 1;
                i %= 3;
                //paths[paths.length - 1] = axesPaths[i];
            }, 5000);
            
            })();
            }}}}

        </script>
    </body>
</html>
